package com.zhentao.service.impl;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhentao.common.admin.utils.AdminUserPermissionUtils;
import com.zhentao.common.market.ChargeMarketParams;
import com.zhentao.core.ChargeCoreFeignApi;
import com.zhentao.mapper.ChargeCouponMapper;
import com.zhentao.mapper.ChargeUserCouponMapper;
import com.zhentao.market.ChargeMarketThreadUtils;
import com.zhentao.model.common.dtos.PermissionResult;
import com.zhentao.model.common.dtos.ResponseResult;
import com.zhentao.model.common.enums.AppHttpCodeEnum;
import com.zhentao.model.pojo.core.ChargeStationInfo;
import com.zhentao.model.pojo.market.ChargeCoupon;
import com.zhentao.model.pojo.market.ChargeCouponCondition;
import com.zhentao.model.pojo.market.ChargeCouponParam;
import com.zhentao.model.pojo.market.ChargeUserCoupon;
import com.zhentao.model.pojo.market.dto.ChargeAdminCouponDto;
import com.zhentao.model.pojo.market.dto.ChargeAdminMarker;
import com.zhentao.model.pojo.market.vo.ChargeAdminMarkeyVo;
import com.zhentao.model.pojo.market.vo.CouponVo;
import com.zhentao.model.pojo.user.ChargeUser;
import com.zhentao.service.ChargeCouponConditionService;
import com.zhentao.service.ChargeCouponService;
import com.zhentao.service.CouponAsyncService;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.C;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.zhentao.common.admin.enums.AdminPermsEnum.*;
import static com.zhentao.common.market.ChargeMarketCommon.CHARGE_USER_SETNX_KEY;
import static com.zhentao.model.common.enums.AppHttpCodeEnum.*;

/**
 * @author Wl177
 * @description 针对表【charge_coupon】的数据库操作Service实现
 * @createDate 2024-12-23 15:44:19
 */
@Service
@Slf4j
public class ChargeCouponServiceImpl extends ServiceImpl<ChargeCouponMapper, ChargeCoupon>
        implements ChargeCouponService {
    @Autowired
    private ChargeCouponConditionService conditionService;
    @Autowired
    private CouponAsyncService couponAsyncService;
    @Autowired
    private RedissonClient redissonClient;
    @Resource
    private ChargeUserCouponMapper userCouponMapper;
    @Resource
    ChargeCoreFeignApi chargeCoreFeignApi;
    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * @param param
     * @return com.zhentao.model.common.dtos.ResponseResult
     * @description 查询待领取的优惠卷列表
     * @author 振涛教育_小Q
     * @date 2024/12/26 14:02
     */
    @Override
    public ResponseResult chargeCouponList(ChargeCouponParam param) {
        // 判断参数是否为空
        if (param == null) {
            return ResponseResult.errorResult(SERVER_ERROR);
        }

        // 分页
        Page<ChargeCoupon> page = new Page<>(param.getPageNum(), param.getPageSize());
        this.page(page, Wrappers.<ChargeCoupon>lambdaQuery()
                .eq(StringUtils.checkValNotNull(param.getStatus()), ChargeCoupon::getStatus, param.getStatus()));

        List<ChargeCoupon> records = page.getRecords();
        try {
            for (int i = 0; i < records.size(); i++) {
                ChargeCoupon chargeCoupon = records.get(i);
                CouponVo vo = new CouponVo();
                BeanUtils.copyProperties(chargeCoupon, vo);
                // 设置优惠卷类型
                vo.setUserTypeName(ChargeMarketParams.CHARGE_MARKET_COUPON_USER_TYPE.get(chargeCoupon.getUseType()));
                // 设置优惠卷是否叠加
                vo.setOverlayName(ChargeMarketParams.CHARGE_MARKET_COUPON_OVERLAY.get(chargeCoupon.getOverlay()));
                // 设置优惠卷的有效期单位
                vo.setPeriodUnitName(ChargeMarketParams.CHARGE_MARKET_COUPON_PERIOD_UNIT);
                // 设置优惠卷的状态
                vo.setCouponStatusName(ChargeMarketParams.CHARGE_MARKET_COUPON_STATUS.get(chargeCoupon.getStatus()));
                if (chargeCoupon.getConditionId() != null) {
                    ChargeCouponCondition condition = conditionService.getById(chargeCoupon.getConditionId());
                    if (condition != null) {
                        vo.setCouponCondition(condition);
                        vo.setTypeName(ChargeMarketParams.CHARGE_MARKET_COUPON_CONDITION_TYPE.get(condition.getType()));
                        // 查询时异步调用一下 检查是否过期  如果过期则 进行修改 异步调用
                        couponAsyncService.checkCouponExpire(chargeCoupon, condition);
                    }
                }
                records.set(i, vo);
            }
        } catch (NullPointerException e) {
            log.info("NullPointerException 异常：", e);
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return ResponseResult.okResult(page);
    }

    /**
     * @param coupon
     * @return com.zhentao.model.common.dtos.ResponseResult
     * @description 点击领取优惠卷
     * @author 振涛教育_小Q
     * @date 2024/12/26 15:39
     */
    @Override
    public ResponseResult addUserCoupon(ChargeCoupon coupon) {
        // 判断参数是否有效
        if (coupon == null) {
            return ResponseResult.errorResult(SERVER_ERROR);
        }
        // 获取当前登录用户
        ChargeUser user = ChargeMarketThreadUtils.getChargeUserThreadLocal();
        // 判断该用户是否已经领取 添加 分布式锁
        RLock lock = redissonClient.getLock(CHARGE_USER_SETNX_KEY + user.getId());
        boolean flag = lock.tryLock();
        if (!flag) {
            log.info("不允许重复领取！！！");
            return ResponseResult.errorResult(CHARGE_MARKET_COUPON);
        }


        // 异步减少 库存
        boolean bool = couponAsyncService.reduceStock(coupon, user.getId());
        if (!bool) return ResponseResult.errorResult(450, "库存或您的积分不足了！！");
        // 添加优惠卷
        ChargeUserCoupon userCoupon = new ChargeUserCoupon();
        userCoupon.setUserId(user.getId());
        userCoupon.setCouponId(coupon.getId());
        userCoupon.setCreateTime(LocalDateTime.now());
        userCoupon.setStatus(0);
        userCouponMapper.insert(userCoupon);
        // TODO 修改对应的充电桩 id

        log.info("用户成功领取优惠卷，用户id为：{}", user.getId());
        return ResponseResult.okResult(SUCCESS);
    }

    /*
    处理已经使用过的优惠券
 */
    @Override
    public ResponseResult updateBatchByIdCouponStatus(List<Integer> couponIds) {
        boolean flag = false;
        if (couponIds == null && couponIds.size() > 0) {
            return ResponseResult.errorResult(SERVER_ERROR);
        }
        for (Integer couponId : couponIds) {
            ChargeUserCoupon byId = userCouponMapper.selectById(couponId);
            byId.setStatus(1);
            byId.setUseTime(new Date());
            userCouponMapper.updateById(byId);
            flag = true;
            log.info("优惠券已经使用：{}", couponId);
        }
        return flag ? ResponseResult.okResult(SUCCESS) : ResponseResult.errorResult(SERVER_ERROR);
    }

    @Override
    public PermissionResult AdminMarketAll(ChargeAdminMarker chargeAdminMarker) {
        AdminUserPermissionUtils permissionUtils = new AdminUserPermissionUtils(redisTemplate);
        ResponseResult result = permissionUtils.hasPermission(SYS_COUPON_SELECT);
        if (!(result.getCode() == 200000)) {
            return PermissionResult.ERROR(result.getCode(), result.getErrorMessage());
        }
        if (chargeAdminMarker == null) {
            return PermissionResult.ERROR(400000, "参数错误");
        }

        Page<ChargeAdminMarkeyVo> page = new Page<>(chargeAdminMarker.getPageNum(), chargeAdminMarker.getPageSize());
        List<ChargeCoupon> records = this.list();
        List<ChargeAdminMarkeyVo> chargeAdminMarkeyVos = new ArrayList<>();


        for (ChargeCoupon record : records) {
            ChargeCouponCondition one = conditionService.getOne(Wrappers.<ChargeCouponCondition>lambdaQuery().eq(ChargeCouponCondition::getId, record.getConditionId()));
            ChargeAdminMarkeyVo chargeAdminMarkeyVo = new ChargeAdminMarkeyVo();
            BeanUtils.copyProperties(record, chargeAdminMarkeyVo);
            chargeAdminMarkeyVo.setCondition(one);
            ChargeStationInfo chargeStationInfo = chargeCoreFeignApi.AdminFeignInfo(record.getChargeStationInfoId());
            chargeAdminMarkeyVo.setChargeStationInfo(chargeStationInfo);
            chargeAdminMarkeyVos.add(chargeAdminMarkeyVo);
        }
        page.setRecords(chargeAdminMarkeyVos);
        return PermissionResult.OK(200000, "查询成功", page);
    }

    @Resource
    ChargeCouponConditionService chargeCouponConditionService;

    @Override
    public PermissionResult AdminMarkeyAdd(ChargeAdminCouponDto chargeCoupon) {
        AdminUserPermissionUtils permissionUtils = new AdminUserPermissionUtils(redisTemplate);
        ResponseResult result = permissionUtils.hasPermission(SYS_COUPON_ADD);
        if (!(result.getCode() == 200000)) {
            return PermissionResult.ERROR(result.getCode(), result.getErrorMessage());
        }
        ChargeCouponCondition chargeCouponCondition = new ChargeCouponCondition();
        BeanUtils.copyProperties(chargeCoupon, chargeCouponCondition);
        chargeCouponCondition.setCreateTime(LocalDateTime.now());
        boolean save1 = chargeCouponConditionService.save(chargeCouponCondition);
        if (!save1){
            return PermissionResult.ERROR(500000, "添加失败");
        }

        if (chargeCoupon == null) {
            return PermissionResult.ERROR(400000, "参数错误");
        }
        chargeCoupon.setConditionId(chargeCouponCondition.getId());
        if (chargeCoupon.getChargeStationInfoId() == null) {
            chargeCoupon.setUseType(0);
        } else {
            chargeCoupon.setUseType(1);
        }

        boolean save = this.save(chargeCoupon);
        return save ? PermissionResult.OK(200000, "添加成功") : PermissionResult.ERROR(500000, "添加失败");

    }

    @Override
    public PermissionResult AdminMarkeyUpdate(ChargeAdminCouponDto condition) {
        AdminUserPermissionUtils permissionUtils = new AdminUserPermissionUtils(redisTemplate);
        ResponseResult result = permissionUtils.hasPermission(SYS_COUPON_EDIT);
        if (!(result.getCode() == 200000)) {
            return PermissionResult.ERROR(result.getCode(), result.getErrorMessage());
        }
        if (condition == null) {
            return PermissionResult.ERROR(400000, "参数错误");
        }
        ChargeCouponCondition chargeCouponCondition = new ChargeCouponCondition();
        BeanUtils.copyProperties(condition, chargeCouponCondition);
        chargeCouponCondition.setId(condition.getConditionId());


        boolean b = chargeCouponConditionService.updateById(chargeCouponCondition);
        if (b){
            ChargeCoupon chargeCoupon = new ChargeCoupon();
            BeanUtils.copyProperties(condition, chargeCoupon);
            if (chargeCoupon.getChargeStationInfoId()!=null){
                chargeCoupon.setUseType(1);
            }
            boolean b1 = this.updateById(chargeCoupon);
            return b1 ? PermissionResult.OK(200000, "修改成功") : PermissionResult.ERROR(500000, "修改失败");
        }
        return PermissionResult.ERROR(500000, "修改失败");
    }

    @Override
    public PermissionResult AdminMarkeyDelete(ChargeCoupon chargeCoupon) {
        AdminUserPermissionUtils permissionUtils = new AdminUserPermissionUtils(redisTemplate);
        ResponseResult result = permissionUtils.hasPermission(SYS_COUPON_DEL);
        if (!(result.getCode() == 200000)) {
            return PermissionResult.ERROR(result.getCode(), result.getErrorMessage());
        }
        if (chargeCoupon == null) {
            return PermissionResult.ERROR(400000, "参数错误");
        }
        boolean b = chargeCouponConditionService.removeById(chargeCoupon.getConditionId());
        if (b){
            boolean b1 = this.removeById(chargeCoupon.getId());
            return b1 ? PermissionResult.OK(200000, "删除成功") : PermissionResult.ERROR(500000, "删除失败");
        }
        return PermissionResult.ERROR(500000, "删除失败");
    }
}




